package com.market.member.service.auth;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.cloudauth20190307.Client;
import com.aliyun.cloudauth20190307.models.*;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.teaopenapi.models.Config;
import com.block.common.service.LogFactory;
import com.block.db.entity.MemberAuthConfigInfo;
import com.block.storage.config.OssAliConfig;
import com.block.storage.enums.OssTypeEnum;
import com.block.storage.factory.OssFactory;
import com.block.storage.model.OssAuthInfoParam;
import com.market.member.constant.AuthConstant;
import com.market.member.enums.AuthStatusEnum;
import com.market.member.model.dto.AuthHandleDTO;
import com.market.member.model.dto.AuthQueryDTO;
import com.market.member.model.dto.AuthRequestDTO;
import com.market.member.model.result.AuthHandleResult;
import com.market.member.model.result.AuthQueryResult;
import com.market.member.model.result.AuthRequestResult;
import com.market.member.service.IAuthService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class AliAuthService implements IAuthService {

    private static final Logger log = LogFactory.getCommLog();

    @Autowired
    OssAliConfig ossAliConfig;

    @Override
    public AuthHandleResult handleAuthInfo(MemberAuthConfigInfo authConfigInfo, AuthHandleDTO authHandleDTO) {
        return null;
    }

    @Override
    public AuthRequestResult getAuthConfigInfo(AuthRequestDTO authRequestDTO, MemberAuthConfigInfo authConfigInfo){

        // 初始化请求对象
        InitFaceVerifyRequest request = new InitFaceVerifyRequest();
        request.setSceneId(Long.valueOf(authConfigInfo.getSceneId()));
        request.setOuterOrderNo(authRequestDTO.getOrderNo());
        request.setProductCode(authConfigInfo.getProductCode());
        request.setModel(authConfigInfo.getProductModel());
        request.setMetaInfo(authRequestDTO.getReqData());
        request.setCallbackUrl(authConfigInfo.getNoticeUrl());
        request.setCallbackToken(authRequestDTO.getOrderNo());
        request.setCertType("IDENTITY_CARD");
        request.setCertName(authRequestDTO.getCertName());
        request.setCertNo(authRequestDTO.getCertNo());

        log.info("【实人认证】【请求认证数据】【request】{}", JSON.toJSONString(request));
        InitFaceVerifyResponse response = this.getFaceVerifyResponse(request, authConfigInfo);
        log.info("【实人认证】【请求认证数据】【response】{}", JSON.toJSONString(response));

        AuthRequestResult authRequestResult = new AuthRequestResult();
        authRequestResult.setOrderNo(authRequestDTO.getOrderNo());
        authRequestResult.setSuccess(false);
        if (ObjectUtil.isEmpty(response)){
            return authRequestResult;
        }
        if (!StrUtil.equals("200", String.valueOf(response.getStatusCode()))){
            return authRequestResult;
        }
        InitFaceVerifyResponseBody body = response.getBody();
        if (!StrUtil.equals("200", String.valueOf(body.getCode()))){
            authRequestResult.setCode(body.getCode());
            authRequestResult.setMessage(body.getMessage());
            return authRequestResult;
        }

        InitFaceVerifyResponseBody responseBody = response.getBody();

        InitFaceVerifyResponseBody.InitFaceVerifyResponseBodyResultObject resultObject = responseBody.getResultObject();
        String certifyId = resultObject.getCertifyId();

        authRequestResult.setResultInfo(JSON.toJSONString(resultObject));
        authRequestResult.setResultData(certifyId);
        authRequestResult.setOutOrderNo(certifyId);
        if (StrUtil.isEmpty(certifyId)){
            authRequestResult.setSuccess(false);
        }else{
            authRequestResult.setSuccess(true);
        }

        return authRequestResult;
    }

    /**
     * 查询认证结果
     * @param authQueryDTO
     * @param authConfigInfo
     * @return
     */
    @Override
    public AuthQueryResult queryAuthVerifyResult(AuthQueryDTO authQueryDTO, MemberAuthConfigInfo authConfigInfo) throws Exception {

        // 通过以下代码创建API请求并设置参数。
        DescribeFaceVerifyRequest request = new DescribeFaceVerifyRequest();
        // 请输入场景ID+L。
        request.setSceneId(Long.valueOf(authConfigInfo.getSceneId()));
        request.setCertifyId(authQueryDTO.getOutOrderNo());

        // 推荐，支持服务路由。
        DescribeFaceVerifyResponse response = this.describeFaceVerifyAutoRoute(request, authConfigInfo);
        System.out.println(JSON.toJSONString(response));

        DescribeFaceVerifyResponseBody responseBody = response.getBody();
        String code = responseBody.getCode();
        String message = responseBody.getMessage();

        AuthQueryResult authQueryResult = new AuthQueryResult();
        authQueryResult.setOrderNo(authQueryDTO.getOrderNo());
        authQueryResult.setOutOrderNo(authQueryDTO.getOutOrderNo());
        if (!StrUtil.equals(code, "200")){
            authQueryResult.setSuccess(false);
            authQueryResult.setResultInfo(StrUtil.format("code:{};msg:{}", code, message));
            return authQueryResult;
        }
        authQueryResult.setSuccess(true);

        // 查询成功
        DescribeFaceVerifyResponseBody.DescribeFaceVerifyResponseBodyResultObject resultObject = responseBody.getResultObject();
        authQueryResult.setResultInfo(JSON.toJSONString(resultObject));

        String passed = resultObject.getPassed();
        if (StrUtil.equals(passed, "T")){
            authQueryResult.setAuthStatus(AuthStatusEnum.SUCCESS.getValue());
        }else{
            authQueryResult.setAuthStatus(AuthStatusEnum.FAILED.getValue());
        }

        JSONObject materialInfoObject = JSONObject.parseObject(resultObject.getMaterialInfo());

//        JSONObject ocrIdCardInfoObject = materialInfoObject.getJSONObject("ocrIdCardInfo");
//        String certNo = ocrIdCardInfoObject.getString("certNo");
//        String certName = ocrIdCardInfoObject.getString("certName");
//        authQueryResult.setIdCard(certNo);
//        authQueryResult.setRealname(certName);

//        JSONObject ocrPictureFrontObject = materialInfoObject.getJSONObject("ocrPictureFront");
//        String ossBucketName = ocrPictureFrontObject.getString("ossBucketName");
//        String ossIdFaceObjectName = ocrPictureFrontObject.getString("ossIdFaceObjectName");
//        String ossIdNationalEmblemObjectName = ocrPictureFrontObject.getString("ossIdNationalEmblemObjectName");

        JSONObject facialPictureFrontObject = materialInfoObject.getJSONObject("facialPictureFront");
        String facialOssObjectName = facialPictureFrontObject.getString("ossObjectName");
        String ossBucketName = facialPictureFrontObject.getString("ossBucketName");

//        String faceObjectKey = StrUtil.format(AuthConstant.FACE_OBJECT_KEY_FORMAT, authQueryDTO.getUid(), authQueryDTO.getOrderNo(), authQueryDTO.getOrderNo());
//        String nationalObjectKey = StrUtil.format(AuthConstant.NATIONAL_OBJECT_KEY_FORMAT, authQueryDTO.getUid(), authQueryDTO.getOrderNo(), authQueryDTO.getOrderNo());
        String facialObjectKey = StrUtil.format(AuthConstant.FACIAL_OBJECT_KEY_FORMAT, authQueryDTO.getUid(), authQueryDTO.getOrderNo(), authQueryDTO.getOrderNo());

        OssAuthInfoParam ossAuthInfoParam = new OssAuthInfoParam();
        ossAuthInfoParam.setEndpoint(ossAliConfig.getPriEndpoint());
        ossAuthInfoParam.setRegionId(ossAliConfig.getPriRegionId());
        ossAuthInfoParam.setBucketName(ossAliConfig.getPriBucketName());

        // 备份用户认证资料
//        boolean faceRes = OssFactory.getService(OssTypeEnum.ALIYUN.getType())
//                .copyObjectKey(ossBucketName, ossIdFaceObjectName, ossAliConfig.getPriBucketName(), faceObjectKey, ossAuthInfoParam);
//        boolean nationalRes = OssFactory.getService(OssTypeEnum.ALIYUN.getType())
//                .copyObjectKey(ossBucketName, ossIdNationalEmblemObjectName, ossAliConfig.getPriBucketName(), nationalObjectKey, ossAuthInfoParam);
        boolean facialRes = OssFactory.getService(OssTypeEnum.ALIYUN.getType())
                .copyObjectKey(ossBucketName, facialOssObjectName, ossAliConfig.getPriBucketName(), facialObjectKey, ossAuthInfoParam);

//        if (faceRes && nationalRes && facialRes){
//            authQueryResult.setAuthSource(AuthStatusEnum.SUCCESS.getValue());
//            authQueryResult.setIdCardFrontUrl(ossAliConfig.getPriHostUrl() + faceObjectKey);
//            authQueryResult.setIdCardBackUrl(ossAliConfig.getPriHostUrl() + nationalObjectKey);
//            authQueryResult.setPersonImageUrl(ossAliConfig.getPriHostUrl() + facialObjectKey);

        if (facialRes){
            authQueryResult.setAuthSource(AuthStatusEnum.SUCCESS.getValue());
            authQueryResult.setPersonImageUrl(ossAliConfig.getPriHostUrl() + facialObjectKey);
        }else{
            authQueryResult.setAuthStatus(AuthStatusEnum.ERROR.getValue());
        }

        return authQueryResult;
    }

    private DescribeFaceVerifyResponse describeFaceVerifyAutoRoute(DescribeFaceVerifyRequest request, MemberAuthConfigInfo authConfigInfo) {
        // 第一个为主区域Endpoint，第二个为备区域Endpoint。
        List<String> endpoints = JSON.parseArray(authConfigInfo.getExtData(), String.class);
        DescribeFaceVerifyResponse lastResponse = null;
        for (String endpoint : endpoints) {
            try {
                Config config = new Config();
                config.setAccessKeyId(authConfigInfo.getAppKey());
                config.setAccessKeySecret(authConfigInfo.getAppSercret());
                config.setEndpoint(endpoint);
                Client client = new Client(config);
                DescribeFaceVerifyResponse response = client.describeFaceVerify(request);

                lastResponse = response;
                // 服务端错误，切换到下个区域调用。
                if (response != null && "500".equals(response.getStatusCode())) {
                    continue;
                }
                return response;
            } catch (Exception e) {
                // 网络异常，切换到下个区域调用。
                if (e.getCause() instanceof TeaException) {
                    TeaException teaException = ((TeaException)e.getCause());
                    if (teaException.getData() != null && "ServiceUnavailable".equals(
                            teaException.getData().get("Code"))) {
                        continue;
                    }
                }

                if (e.getCause() instanceof TeaUnretryableException) {
                    continue;
                }
            }
        }

        return lastResponse;
    }

    /**
     * @param request
     * @param authConfigInfo
     * @return
     */
    private InitFaceVerifyResponse getFaceVerifyResponse(InitFaceVerifyRequest request, MemberAuthConfigInfo authConfigInfo){

        InitFaceVerifyResponse lastResponse = null;
        List<String> endpointList = JSON.parseArray(authConfigInfo.getExtData(), String.class);
        for (String endpoint: endpointList){
            try {

                Config config = new Config();
                config.setAccessKeyId(authConfigInfo.getAppKey());
                config.setAccessKeySecret(authConfigInfo.getAppSercret());
                config.setEndpoint(endpoint);
                Client client = new Client(config);
                InitFaceVerifyResponse response = client.initFaceVerify(request);

                // 服务端错误，切换到下个区域调用。
                if (response != null && "500".equals(response.getStatusCode())) {
                    continue;
                }
                lastResponse = response;
                break;
            }catch (Exception exception){
                // 网络异常，切换到下个区域调用。
                if (exception.getCause() instanceof TeaException) {
                    TeaException teaException = ((TeaException)exception.getCause());
                    if (teaException.getData() != null && "ServiceUnavailable".equals(
                            teaException.getData().get("Code"))) {
                        continue;
                    }
                }
                if (exception.getCause() instanceof TeaUnretryableException) {
                    continue;
                }
            }
        }
        return lastResponse;
    }


}
